<?php

namespace Modules\Inventory\Repository;

use App\Services\InventoryService;
use App\Services\KingDeeService;
use App\Services\UnitService;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Modules\Inventory\Models\InventoryOrder;
use Modules\Inventory\Models\InventoryOrderDetail;
use App\Enums\InvTransDocType;
use Modules\Inventory\Models\InventoryPlanDiff;
use App\Enums\InventoryOrderStatus;

/**
 * 盘点单相关
 * Class InventoryOrderRepository
 * @package Modules\Inventory\Repository
 */
class InventoryOrderRepository
{

    /**
     * 盘点单列表
     * @param $params
     * @return mixed
     */
    static public function getList($params){

        $builder = self::getWhere($params);

        $limit = isset($request['limit']) ? $request['limit'] : 100;

        $list = $builder->orderBy('id','desc')->with(['plan'])->whereHas('plan',function($query) use($params){
            if(isset($params['plan_no']) && $params['plan_no'] != ''){
                $query->where('plan_no',$params['plan_no']);
            }
        })->paginate($limit)->toArray();

        return $list;
    }

    /**
     * 列表条件
     * @param $params
     * @return InventoryOrder
     */
    static public function getWhere($params){

        $builder = new InventoryOrder();
        $canSearchFields = $builder->getFields();
        foreach ($params as $key => $val){
            if(!in_array($key,$canSearchFields) || $val == ''){
                continue;
            }

            if($key == 'status'){
                $builder = $builder->whereIn($key,explode(',',trim($val,',')));
            }else{
                $builder = $builder->where($key,$val);
            }

        }

        return $builder;
    }

    /**
     * 创建盘点单
     * @param $plan
     * @param $orderItem
     */
    static public function createrOrder($plan,$orderItem,$location){

        $orderHeader = self::saveOrderHeader($plan,$location);

        $orderHeader['detail'] = self::saveOrderDetail($plan,$orderHeader,$orderItem);

        return $orderHeader;
    }

    /**
     * 保存盘点单据头
     * @param $plan
     * @return array
     */
    static public function saveOrderHeader($plan,$location){

        $order = [
            'docno'     => UnitService::createDocno('PD'),
            'plan_id'   => $plan->id,
            'org_code'  => $plan->org_code,
            'location'  => $location,
            'status'    => 0,
        ];
        $order['id'] = (new InventoryOrder())->storeBy($order);

        return $order;
    }

    /**
     * 保存盘点单明细
     * @param $plan
     * @param $orderHeader
     * @param $orderItem
     * @return array
     */
    static public function saveOrderDetail($plan,$orderHeader,$orderItem){

        $detail = [];
        foreach ($orderItem as $item){
            $detail[] = [
                'order_id'      => $orderHeader['id'],
                'material_no'   => $item->material_no,
                'wms_code'      => $item->wms_code,
                'location'      => $item->location,
                'lot_num'       => $item->lot_num,
                'unit'          => $item->unit,
                'qty'           => $item->qty,
                'stock_qty'     => $plan->default_qty,
                'remark'        => '',
                'creator_id'    => Auth::guard(getGuardName())->id(),
                'created_at'    => time()
            ];
        }

        InventoryOrderDetail::insert($detail);

        return $detail;

    }

    /**
     * 按盘点方案审核盘点单
     * @param $planId
     */
    static public function verify($planId){

        //盘点方案
        $plan = InventoryPlanRepository::getFirstPlanById($planId);
        if($plan->status == 2){
            throw new \Exception('盘点方案已推送金蝶');
        }

        //盘点单列表
        $orderList = self::getOrderByPlanId($planId)->toArray();

        $orderId = array_column($orderList,'id');

        foreach ($orderList as $item){
            if($item['status'] != InventoryOrderStatus::FINISH->value){
                throw new \Exception("盘点单[{$item['docno']}]未审核");
            }
        }

        try{

            DB::beginTransaction();

            foreach ($orderList as $orderItem){

                foreach ($orderItem['detail'] as $detailItem){

                    $diffQty = $detailItem['stock_qty'] - $detailItem['qty'];

                    if($diffQty > 0){
                        //盘盈入库
                        InventoryService::addInv([
                            'org_code'      => $orderItem['org_code'],
                            'cargo_code'    => $orderItem['org_code'],
                            'supplier_code' => $orderItem['docno'],
                            'doc_id'        => $orderItem['id'],
                            'docno'         => $orderItem['docno'],
                            'doc_type'      => InvTransDocType::INVENTORY_ORDER->value,
                            'material_no'   => $detailItem['material_no'],
                            'location'      => $detailItem['location'],
                            'qty'           => $diffQty,
                            'unit'          => $detailItem['unit'],
                            'lotnum'        => $detailItem['lot_num'],
                        ]);
                    }elseif($diffQty < 0){
                        //盘亏出库
                        InventoryService::decInventory(
                            $orderItem['org_code'],
                            $orderItem['docno'],
                            $orderItem['id'],
                            InvTransDocType::INVENTORY_ORDER->value,
                            $detailItem['material_no'],
                            $detailItem['location'],
                            $detailItem['lot_num'],
                            abs($diffQty),
                            $orderItem['org_code']
                        );
                    }
                }

                //设盘点单为盘点完成
                self::updateById($orderItem['id'],['status' => 20]);

            }

            //设盘点方案为已推送
            InventoryPlanRepository::updateById($planId,['status' => 2]);

            //推送金蝶
            self::pushKingDee($plan,$orderId);

            DB::commit();

        }catch (\Exception $e){
            DB::rollBack();
            throw $e;
        }

    }

    /**
     * 盘点单差异推送金蝶（盘盈盘亏）
     * @param $planId
     * @param $orderId
     * @return string
     */
    static public function pushKingDee($plan,$orderId){

        //查询差异数
        $diffOrder = InventoryOrderDetailRepository::getDiffQtyByOrderId($orderId);
        if($diffOrder->isEmpty()){
            return '';
        }

        //盘盈
        $gain = [];
        //盘亏
        $loss = [];
        foreach ($diffOrder as $item){

            //跳过没差异的
            if($item->diff_qty == 0){
                continue;
            }

            $kingdeeItem = [
                'FSTOCKID'      => $item->wms_code,//仓库代码
                'FQTY'          => abs($item->diff_qty),//数量
                'FGIVEAWAY'     => false,//赠品
                'FMATERIALID'   => $item->material_no,//品号
                'FOwnerTypeId'  => 'BD_OwnerOrg',//货主类型
                'FOwnerId'      => $plan->org_code,//货主编码
                'FUNITID'       => $item->material->funit_number,//单位编码
            ];

            if($item->diff_qty > 0){
                $gain[] = $kingdeeItem;
            }elseif($item->diff_qty < 0){
                $loss[] = $kingdeeItem;
            }

        }
        //盘亏-其他出库
        self::pushOtherOut($plan,$loss);
        //盘盈-其他入库
        self::pushOtherInbound($plan,$gain);


    }

    /**
     * 盘亏推送(其他出库单)
     * @param $planInfo
     * @param $kingdeeItem
     */
    static public function pushOtherOut($planInfo,$kingdeeItem){
        if(empty($kingdeeItem)){
            return true;
        }

        $docno = $planInfo->plan_no . '-1';

        $kingdeeOrder = [
            'FBillNo'       => $docno,
            'FDATE'         => date('Y-m-d H:i:s',time()),
            'FBILLTYPEID'   => "STK_MisDelivery",
            'FORGID'        => $planInfo->org_code,//组织
            'FDESCRIPTION'  => 'QW005',//盘亏出库标识,
            // 'FSRCBILLNO'=>'',
            'FEntity'       => $kingdeeItem,
        ];

        $diff = [];
        foreach($kingdeeItem as $item){
            $diff[] = [
                'org_code'      => $planInfo->org_code,
                'cargo_code'    => $planInfo->org_code,
                'plan_id'       => $planInfo->id,
                'docno'         => $docno,
                'wms_code'      => $item['FSTOCKID'],
                'material_no'   => $item['FMATERIALID'],
                'unit'          => $item['FUNITID'],
                'qty'           => $item['FQTY'],
                'diff_type'     => 'QW005',
                'creator_id'    => UnitService::getUserId(),
                'created_at'    => time(),
                'updated_at'    => time()
            ];
        }
        InventoryPlanDiff::insert($diff);

        (new KingDeeService())->form('TVJB_DJWMSDJ')->invokeSave($kingdeeOrder);

    }

    /**
     * 盘盈推送（其他入库单）
     * @param $planInfo
     * @param $kingdeeItem
     * @return bool
     */
    static public function pushOtherInbound($planInfo,$kingdeeItem){
        if(empty($kingdeeItem)){
            return true;
        }

        $docno = $planInfo->plan_no . '-2';

        $kingdeeOrder = [
            'FBillNo'       => $docno,
            'FDATE'         => date('Y-m-d H:i:s',time()),
            'FBILLTYPEID'   => "STK_MISCELLANEOUS",
            'FORGID'        => $planInfo->org_code,//组织
            'FDESCRIPTION'  => 'QW001',//盘盈入库标识
            // 'FSRCBILLNO'=>'',
            'FEntity'       => $kingdeeItem,
        ];

        $diff = [];
        foreach($kingdeeItem as $item){
            $diff[] = [
                'org_code'      => $planInfo->org_code,
                'cargo_code'    => $planInfo->org_code,
                'plan_id'       => $planInfo->id,
                'docno'         => $docno,
                'wms_code'      => $item['FSTOCKID'],
                'material_no'   => $item['FMATERIALID'],
                'unit'          => $item['FUNITID'],
                'qty'           => $item['FQTY'],
                'diff_type'     => 'QW001',
                'creator_id'    => UnitService::getUserId(),
                'created_at'    => time(),
                'updated_at'    => time()
            ];
        }
        InventoryPlanDiff::insert($diff);

        (new KingDeeService())->form('TVJB_DJWMSDJ')->invokeSave($kingdeeOrder);
    }

    /**
     * 根据盘点方案查询所有盘点单
     * @param $planId
     * @return mixed
     */
    static public function getOrderByPlanId($planId){
        return InventoryOrder::with('detail')->where('plan_id',$planId)->get();
    }

    /**
     * 根据id获取盘点单
     * @param $id
     * @return mixed
     */
    static public function getOrderById($id){
        return InventoryOrder::find($id);
    }

    /**
     * 根据id修改单据头内容
     * @param $orderId
     * @param $data
     * @return mixed
     */
    static public function updateById($orderId,$data){
        return InventoryOrder::where('id',$orderId)->update($data);
    }

    /**
     * 设盘点单为已审核
     * @param $id
     * @return mixed
     */
    static public function inventoryOrderVerify($id){
        return self::updateById($id,['status' => InventoryOrderStatus::FINISH->value]);
    }

}
